﻿using Collection.Entities;
using Super.Collection.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace Super.Collection.Core.Providers.Welfare
{
	/// <summary>
	/// 中国福彩网（http://www.chinafcw.com.cn/）
	/// </summary>
	public class ChinaWelfareLotteryNet : DataProvider
	{
		/// <summary>
		/// 公告数据正则表达式
		/// </summary>
		private string BulletinRegex
		{
			get
			{
				return @"(?<=>)(?'date'\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}\.\d{1,3})(?=<\/div>)[\s\S]*?(?<=>)(?'serialNumber'\d{4,})(?=<\/a>)[\s\S]*?(?'redNumbers'(\d{2}\|){5}\d{2})[\s\S]*?(?<=>)(?'blueNumber'\d{2})(?=<\/a>)[\s\S]*?(?<=<td><div align=.{8}>)(?'superSunday'\d*)</div></td>";
			}
		}

		/// <summary>
		/// 详情数据正则
		/// </summary>
		private string DetailsRegex
		{
			get
			{
				return @"(?<=>)(?'description'\w{2,}奖)(?=<\/td>)[\s\S]*?(?<=>)(?'quantity'\d*?)(?=<\/td>)[\s\S]*?(?<=>)(?'unitPrice'\d*?)(?=<\/td>)";
			}
		}

		/// <summary>
		/// 公告数据正则表达式(另一半数据信息)
		/// </summary>
		private string BulletinOtherHalfRegex
		{
			get
			{
				return @"(?<=\s+)(?'sales'\d+)(?=<br>)[\s\S]*?(?'cumulative'\s+\d+\s+)";
			}
		}

		/// <summary>
		/// 详情Url
		/// </summary>
		private string DetailUrl
		{
			get
			{
				return "http://www.95189518.cn/ulWinInfo.do?issueNumber={0}&method=detail";
			}
		}


		/// <summary>
		/// 获取综合报告接口
		/// </summary>
		/// <param name="url">提供者的地址</param>
		/// <param name="encoding">文档解析的编码</param>
		/// <returns>返回报告列表</returns>
		public override List<Announcement> GetAnnouncements(string url, Encoding encoding)
		{
			string detailUrl = this.DetailUrl;
			List<Announcement> lotteryReports = new List<Announcement>();
			List<LotteryNumber> numbers;
			List<LotteryDetails> details;
			LotteryBriefing briefing1;
			LotteryBriefing briefing2;
			string document = this.GetDocument(url, encoding);
			MatchCollection matchCollections = Regex.Matches(document, this.BulletinRegex, RegexOptions.IgnoreCase);
			for (int i = 0; i < matchCollections.Count; i++)
			{
				briefing1 = this.GetLotteryBriefing(matchCollections[i]);
				numbers = this.GetLotteryNumbers(matchCollections[i]);
				details = this.GetLotteryDetails(string.Format(detailUrl, briefing1.SerialNumber), encoding);
				briefing2 = this.GetLotteryBriefing(string.Format(detailUrl, briefing1.SerialNumber), encoding);
				briefing1.Sales = briefing2.Sales;
				briefing1.Cumulative = briefing2.Cumulative;
				lotteryReports.Add(new Announcement
				{
					LotteryBriefing = briefing1,
					LotteryNumbers = numbers,
					LotteryDetails = details
				});
			}
			return lotteryReports;
		}

		/// <summary>
		/// 从正则匹配的结果中创建中奖公告信息（部分）
		/// </summary>
		/// <param name="match">匹配结果项</param>
		/// <returns></returns>
		private LotteryBriefing GetLotteryBriefing(Match match)
		{
			string lotteryDate = match.Groups["date"].Value;
			string serialNumber = match.Groups["serialNumber"].Value;
			LotteryBriefing bulletin = new LotteryBriefing
			{
				LotteryDates = DateTime.Parse(lotteryDate),
				Provider = 1,
				LotteryTicketId = 1,
				SerialNumber = serialNumber
			};
			return bulletin;
		}

		/// <summary>
		/// 获取公告信息(部分)
		/// </summary>
		private LotteryBriefing GetLotteryBriefing(string url, Encoding encoding)
		{
			LotteryBriefing bulletin = new LotteryBriefing();
			string document = this.GetDocument(url, encoding);
			MatchCollection matchCollection = Regex.Matches(document, this.BulletinOtherHalfRegex, RegexOptions.IgnoreCase);
			for (int i = 0; i < matchCollection.Count; i++)
			{
				bulletin.Sales = decimal.Parse(matchCollection[i].Groups["sales"].Value);
				bulletin.Cumulative = decimal.Parse(matchCollection[i].Groups["cumulative"].Value);
			}
			return bulletin;
		}

		/// <summary>
		/// 获取中奖号码
		/// </summary>
		/// <param name="number"></param>
		/// <param name="blue">蓝色球</param>
		/// <returns></returns>
		private List<LotteryNumber> GetLotteryNumbers(Match match)
		{
			string red = match.Groups["redNumbers"].Value;
			string blue = match.Groups["blueNumber"].Value;
			string superSunday = match.Groups["superSunday"].Value;
			List<LotteryNumber> lotteryNumbers = new List<LotteryNumber>();
			string[] redNumbers = red.Split('|');
			for (short i = 0; i < redNumbers.Length; i++)
			{
				lotteryNumbers.Add(new LotteryNumber
				{
					Location = (short)(i + 1),
					Number = short.Parse(redNumbers[i])
				});
			}
			lotteryNumbers.Add(new LotteryNumber
			{
				Location = 7,
				Number = short.Parse(blue)
			});
			if (!string.IsNullOrEmpty(superSunday))
			{
				lotteryNumbers.Add(new LotteryNumber
				{
					Location = 8,
					Number = short.Parse(superSunday)
				});
			}
			return lotteryNumbers;
		}

		/// <summary>
		/// 获取中奖详情
		/// </summary>
		/// <param name="url">提供者的地址</param>
		/// <param name="encoding">文档解析的编码</param>
		/// <returns>返回中奖详情列表</returns>
		private List<LotteryDetails> GetLotteryDetails(string url, Encoding encoding)
		{
			string quantity, unitPrice;
			List<LotteryDetails> lotteryDetails = new List<LotteryDetails>();
			string document = this.GetDocument(url, encoding);
			MatchCollection matchCollections = Regex.Matches(document, this.DetailsRegex, RegexOptions.IgnoreCase);
			for (byte i = 0; i < matchCollections.Count; i++)
			{
				quantity = matchCollections[i].Groups["quantity"].Value;
				unitPrice = matchCollections[i].Groups["unitPrice"].Value;
				lotteryDetails.Add(new LotteryDetails
				{
					Quantity = string.IsNullOrEmpty(quantity) ? 0 : int.Parse(quantity),
					RewardLevels = i == (byte)(matchCollections.Count - 1) ? (byte)24 : (byte)(i + 1),
					UnitPrice = string.IsNullOrEmpty(unitPrice) ? 0 : int.Parse(unitPrice),
				});
			}
			return lotteryDetails;
		}

		public override NLotteryDraw GetLatestLotteryDraw()
		{
			String listUrl = "http://www.chinafcw.com.cn/ulWinInfo.do?method=list&menuType=5";
			String detailUrl = "http://www.chinafcw.com.cn/ulWinInfo.do?issueNumber={0}&method=detail";

			String listDocument = this.GetDocument(listUrl, Encoding.GetEncoding("GBK"));
			String pattern = @"<tr class=""ncolor"">\s*?<td><div align=""center"">(?<date>\d{4}-\d{2}-\d{2})[\s0:\.]*</div></td>\s*<td><div align=""center""><a href=""[\s\S]*?"">(?<issue>[\d]{7})</a></div></td>\s*<td class=""kjhfont""><div align=""center""><a href=""[\s\S]*?"">(?<number>[\d|]*?)</a></div></td>\s*<td class=""kjbfont""><div align=""center""><a href=""[\s\S]*?"">(?<snumber>[\d]*?)</a></div></td>\s*<td><div align=""center""></div></td>\s*</tr>";
			var firtMatch = Regex.Match(listDocument, pattern);

			NLotteryDraw draw = new NLotteryDraw();

			draw.Issuer = "福彩";
			draw.Game = "双色球";
			draw.DrawDate = DateTime.Parse(firtMatch.Groups["date"].Value);
			draw.IssueNumber = firtMatch.Groups["issue"].Value;
			draw.Numbers = firtMatch.Groups["number"].Value.Replace("|", ",");
			draw.BonusNumbers = firtMatch.Groups["snumber"].Value;

			NLotteryDraw draw2 = CrawLotteryDraw(draw.IssueNumber);
			draw.Bets = draw2.Bets;
			draw.CumulativeAmount = draw2.CumulativeAmount;
			draw.WinningDetails = draw2.WinningDetails;

			//detailUrl = String.Format(detailUrl, draw.IssueNumber);

			//var details = this.GetLotteryDetails(detailUrl, Encoding.GetEncoding("GBK"));

			//draw.WinningDetails = new List<NWinningDetail>();
			//foreach (var detail in details)
			//{
			//	NWinningDetail wDetail = new NWinningDetail();
			//	wDetail.Serial = detail.RewardLevels;
			//	wDetail.Award = detail.RewardLevels.ToString();
			//	wDetail.NumberOfWinners = detail.Quantity;
			//	wDetail.MoneyPerWinner = detail.UnitPrice;
			//	draw.WinningDetails.Add(wDetail);
			//}

			return draw;
		}

		private NLotteryDraw CrawLotteryDraw(string issueNumber)
		{
			string detailUrl = "http://www.chinafcw.com.cn/ulWinInfo.do?issueNumber={0}&method=detail";
			detailUrl = String.Format(detailUrl, issueNumber);

			string htmlSource = this.GetDocument(detailUrl, Encoding.GetEncoding("GBK"));

			var draw = this.ParseLotteryDraw(htmlSource);
			draw.WinningDetails = this.ParseWinningDetails(htmlSource);
			return draw;
		}

		private NLotteryDraw ParseLotteryDraw(string htmlSource)
		{
			string pattern = @"本期投注金额为\s*(?<Bets>\d*)\s*<br>\W*奖池资金累计为\s*(?<CumulativeAmount>\d*)\s*元";
			NLotteryDraw draw = new NLotteryDraw();
			Match match = Regex.Match(htmlSource, pattern, RegexOptions.IgnoreCase);
			string strBets = match.Groups["Bets"].Value;
			string strCumulativeAmount = match.Groups["CumulativeAmount"].Value;
			long bets, cumulativeAmount;
			if (Int64.TryParse(strBets, out bets))
			{
				draw.Bets = bets;
			}
			if (Int64.TryParse(strCumulativeAmount, out cumulativeAmount))
			{
				draw.CumulativeAmount = cumulativeAmount;
			}
			return draw;
		}

		private List<NWinningDetail> ParseWinningDetails(string htmlSource)
		{
			string pattern = @"(?<=>)(?<Award>\w{2,}奖)(?=<\/td>)[\s\S]*?(?<=>)(?<NumberOfWinners>\d*?)(?=<\/td>)[\s\S]*?(?<=>)(?<MoneyPerWinner>\d*?)(?=<\/td>)";
			List<NWinningDetail> details = new List<NWinningDetail>();
			MatchCollection matches = Regex.Matches(htmlSource, pattern, RegexOptions.IgnoreCase);
			int i = 0;
			foreach (Match match in matches)
			{
				NWinningDetail detail = new NWinningDetail();
				detail.Serial = (byte)(i + 1);
				detail.Award = match.Groups["Award"].Value;
				string strNumberOfWinners = match.Groups["NumberOfWinners"].Value;
				string strMoneyPerWinner = match.Groups["MoneyPerWinner"].Value;
				int numberOfWinners, moneyPerWinner;
				if (Int32.TryParse(strNumberOfWinners, out numberOfWinners))
				{
					detail.NumberOfWinners = numberOfWinners;
				}
				if(Int32.TryParse(strMoneyPerWinner, out moneyPerWinner))
				{
					detail.MoneyPerWinner = moneyPerWinner;
				}
				details.Add(detail);
			}
			return details;
		}
	}
}
